<?php

namespace app\plugins\upload;
use app\exception\CommonException;
use Ramsey\Uuid\Uuid;

class WebUploader
{
    //总共片数
    public $totalNumber;
    //当前第几片
    public $number;
    public $fileId;
    public $topic;
    private $state = 0; //上传中
    private $disk = "";
    private $originPath = "";
    private $absolutePath = "";
    private $destionPath = "";
    private $newFileName = "";


    public function setNumber($number)
    {
        $this->number = $number;
        return $this;
    }

    public function setTotalNumber($totalNumber)
    {
        $this->totalNumber = $totalNumber;
        return $this;
    }

    public function setFileId($fileId)
    {
        $this->fileId = $fileId;
        return $this;
    }




    public function setTopic($topic)
    {
        $this->topic = $topic;
        return $this;
    }
    /**
     * 获取文件存储路径
     * @return void
     */
    public  function init()
    {
        $default = config("filesystem.default");
        if (empty($default)) {
            throw new CommonException("默认文件存储没有配置");
        }
        $disk = config("filesystem.disks")[$default];
        if (empty($disk)) {
            throw new CommonException("存储位置没有配置");
        }
        $this->disk = $disk;

        $tempDir = rtrim(sys_get_temp_dir(),DS);
        $this->originPath = sprintf("%s".DS."%d".DS,$tempDir,$this->fileId);
        return $this;
    }

    public function putFile($content)
    {
        if (!is_dir($this->originPath)) {
            mkdir($this->originPath, 0777, true);
        }
        $filePath = $this->originPath . $this->number;
        try {
            file_put_contents($filePath, $content);
            if ($this->number == $this->totalNumber) {
                $this->merge();
                $this->state = 1;
            }
        } catch (\Exception $e) {
            throw new CommonException($e->getMessage());
        }
    }

    /**
     * 按照访问时间合并文件
     * @return void
     * @throws CommonException
     */
    private function merge()
    {
        $files = glob($this->originPath . "*");
        if ($files === false) {
            throw new CommonException("文件临时目录不存在");
        }
        sort($files);
        $newPath = $this->getDestinationPath();
        $newFileName = $this->getFileName();
        $this->destionPath = rtrim($newPath,DS);
        $this->absolutePath = $this->destionPath . DS . $newFileName;
        try {
            foreach ($files as $file) {
                file_put_contents($this->absolutePath, file_get_contents($file), FILE_APPEND);
                unlink($file);
            }
            rmdir($this->originPath);
        } catch (\Exception $e) {
            throw new CommonException($e->getMessage());
        }
    }

    /**
     * 获取目的路径
     * @return string
     */
    public function getDestinationPath(): string
    {
        if (empty($this->destionPath)) {
            $disk = $this->disk["root"];
            $disk = rtrim($disk, DS);
            $newPath = sprintf("%s".DS."%s".DS."%s", $disk, $this->topic, date("Ymd"));
            if (!is_dir($newPath)) {
                mkdir($newPath, 0777, true);
            }
            $this->destionPath = $newPath;
        }
        return $this->destionPath;
    }

    public function getFileName(): string
    {
        if (empty($this->newFileName)) {
            $fileName = str_replace("-", "", Uuid::uuid4());
            $this->newFileName = sprintf("%s.%s", $fileName, $this->topic);
        }
        return $this->newFileName;
    }

    /**
     * 获取文件存储相对路径
     * @return string
     */
    public function getRealPath(): string
    {
        if (!empty($this->absolutePath)) {
            $url = $this->disk["url"];
            $pos = stripos($this->absolutePath, $url);
            return substr($this->absolutePath, $pos);
        }
        return "";
    }

    /**
     * 获取上传状态
     * @return int
     */
    public function getState(): int
    {
        return $this->state;
    }

    public function getAbsolutePath()
    {
        return $this->absolutePath;
    }

    public function getMimeType(): bool|string
    {

        if (!extension_loaded('fileinfo')) {
            throw new CommonException("finfo未开启");
        }
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mimeType = finfo_file($finfo, $this->absolutePath);
        finfo_close($finfo);
        return $mimeType;
    }
}